﻿using Core.Framework.Model.Common;
using Core.Framework.Redis.Queue_Helper;
using Core.Framework.Util;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Linq;
using Microsoft.AspNetCore.Razor.Language.Intermediate;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.AspNetCore.Http;

namespace Core.ApiClient
{
    /// <summary>
    /// API请求身份验证
    /// </summary>
    public class ApiAuthorizeAttribute : Attribute, IActionFilter
    {


        public ApiAuthorizeAttribute()
        {
        }

        /// <summary>
        /// 请求参数初始值
        /// </summary>
        private void ActionArguments(ActionExecutingContext context, ApiClientInfo client, ApiProjectInfo project)
        {
            foreach (var item in context.ActionArguments)
            {

                // 参数未Null   跳过
                if (null == item.Value)
                    continue;

                //  获取参数类型
                Type t = item.Value.GetType();

                Type[] types = new Type[]{ typeof(int), typeof(DateTime), typeof(string), typeof(long), typeof(int?), typeof(DateTime?), typeof(long?) };

                // 检查参数 是否存在可初始化字段
                foreach (var property in t.GetProperties())
                {

                    if (!types.Contains(property.PropertyType))
                        continue;


                    switch (property.Name.ToLower())
                    {


                        // 用户 ID
                        case "user_key":
                        case "userkey":
                        case "supplierkey":


                            if (property.PropertyType == typeof(int?))
                                property.SetValue(item.Value, client.Key);

                            else if (property.PropertyType == typeof(long?))
                                property.SetValue(item.Value, (long) client.Key);

                            if (property.PropertyType == typeof(int))
                                property.SetValue(item.Value, client.Key);

                            else if (property.PropertyType == typeof(long))
                                property.SetValue(item.Value, (long)client.Key);

                            break;


                        // 项目Token
                        case "projecttoken":
                        case "project_token":

                            var token = property.GetValue(item.Value);
                            if (string.IsNullOrWhiteSpace(token?.ToString()))
                            {
                                property.SetValue(item.Value, client.ProjectToken);
                            }

                            break;


                        // 用户token
                        case "usertoken":

                            property.SetValue(item.Value, client.Token);

                            break;



                        case "addtime":
                        case "regtime":

                            property.SetValue(item.Value, DateTime.Now);

                            break;
                    }
                }

            }
        }

        public void OnActionExecuted(ActionExecutedContext context)
        {
        }

        public void OnActionExecuting(ActionExecutingContext context)
        {



            // 指定【Action】忽略登录验证
            var action = ((ControllerActionDescriptor)context.ActionDescriptor).ActionName;

            var actionType = context.Controller.GetType().GetMethods().Where(a => a.Name == action).FirstOrDefault();

            if (!actionType.IsDefined(typeof(IgnoreAuthorizeAttribute), true))
            {
                var token = context.HttpContext.Request.Headers["itool-token"].ToString();

                if (!string.IsNullOrWhiteSpace(token))
                {
                    var result
                        = RedisQueueHelper.HashGet(RedisQueueHelperParameter.ApiClientByToken, token);

                    if (string.IsNullOrWhiteSpace(result))
                    {
                        context.Result = new JsonResult(new
                        {
                            code = CodeResult.PERMISSION_NO_ACCESS,
                            info = "没有访问权限"
                        });
                        return;
                    }
                    else
                    {
                        var client = ((string)result).TryToEntity<ApiClientInfo>();

                        client.Token = token;

                        context.HttpContext.Items.Add("ClientInfo", client);

                        this.ActionArguments(context,client,(ApiProjectInfo)context.HttpContext.Items["ApiProjectInfo"]);
                    }
                }
                else
                {
                    context.Result = new JsonResult(new
                    {
                        code = CodeResult.INTERFACE_FORBIDDEN,
                        info = "接口禁止访问"
                    });
                    return;
                }
            }

        }
    }
}
